#include <stdio.h>
#include <stdlib.h>

#include "common.h"
#include "tda_wav.h"

status_t adt_wav_new(adt_wav_t ** pp_adt_wav,float * fsamples,int samples_qty, int sample_frecuency, float factor){
	
	status_t status;
	size_t i;
	int * p_aux;
	
	if(pp_adt_wav==NULL || fsamples==NULL) return ERROR_NULL_POINTER;
	
	if((*pp_adt_wav=(adt_wav_t *)malloc(sizeof(adt_wav_t)))==NULL) return ERROR_MEMORY;
	
	adt_wav_set_sample_frecuency(*pp_adt_wav,0);
	adt_wav_set_samples_qty(*pp_adt_wav, 0);
	adt_wav_set_factor(*pp_adt_wav,0);
	(*pp_adt_wav)->samples=NULL;
	
	if((status=adt_wav_set_sample_frecuency(*pp_adt_wav,sample_frecuency))!=OK){
		adt_wav_destroy(pp_adt_wav);
		return status;
	}
		
	if((status=adt_wav_set_samples_qty(*pp_adt_wav, samples_qty))!=OK){
		adt_wav_destroy(pp_adt_wav);
		return status;
	}
	
	if((status=adt_wav_set_factor(*pp_adt_wav,factor))!=OK){
		adt_wav_destroy(pp_adt_wav);
		return status;
	}
	
	if((p_aux=(int *)malloc(samples_qty*sizeof(int)))==NULL){
	adt_wav_destroy(pp_adt_wav);
	return ERROR_MEMORY;
	}
	
	for(i=0;i<samples_qty;i++){
		p_aux[i]=(int)(fsamples[i]*factor);
	}
	
	(*pp_adt_wav)->samples=p_aux;
	
	return OK;
}
status_t adt_wav_destroy(adt_wav_t ** pp_adt_wav){

	if(pp_adt_wav==NULL) return ERROR_NULL_POINTER;
	
	if((*pp_adt_wav)->samples!=NULL){
		free((*pp_adt_wav)->samples);
	}
	
	free(*pp_adt_wav);
	pp_adt_wav=NULL;
	return OK;
}
status_t adt_wav_set_samples_qty(adt_wav_t * p_adt_wav, int samples_qty){
	if(p_adt_wav==NULL) return ERROR_NULL_POINTER;
	if(samples_qty<=0) return ERROR_INVALID_DATA;
	p_adt_wav->samples_qty=samples_qty;
	return OK;

}
status_t adt_wav_set_sample_frecuency(adt_wav_t * p_adt_wav, int sample_frecuency){
	if(p_adt_wav==NULL) return ERROR_NULL_POINTER;
	if(sample_frecuency<=0) return ERROR_INVALID_DATA;
	p_adt_wav->sample_frecuency=sample_frecuency;
	return OK;

}

status_t adt_wav_set_factor(adt_wav_t * p_adt_wav, float factor){
	if(p_adt_wav==NULL) return ERROR_NULL_POINTER;
	if(factor<=0) return ERROR_INVALID_DATA;
	p_adt_wav->factor=factor;
	return OK;
}

status_t write_in_LE(void * data, int bytes, FILE * fo){
	
	size_t i;
	int aux;
	unsigned int * p_aux= (unsigned int *) data;
	
	if(data==NULL || fo==NULL) return ERROR_NULL_POINTER;
	if(bytes<=0) return ERROR_INVALID_DATA;
	
	for(i=0;i<bytes;i++){
		aux=((*p_aux)>>(8*i))&MASK_BYTE1;
		fwrite(&aux,sizeof(char),1,fo);
	}
	return OK;
}

status_t adt_wav_save(adt_wav_t * p_adt_wav, FILE* fo){

	unsigned int aux_int;
	size_t i,j;
	
	if(p_adt_wav==NULL || fo==NULL) return ERROR_NULL_POINTER;
	
	write_in_LE(CHUNK_ID, BYTES_32BIT,fo);
	
	aux_int=36+2*(p_adt_wav->samples_qty);
	write_in_LE(&aux_int, BYTES_32BIT,fo);

	write_in_LE(FORMAT, BYTES_32BIT,fo);
	
	write_in_LE(SUBCHUNK_1_ID, BYTES_32BIT,fo);
	
	aux_int=SUBCHUNK_1_SIZE;
	write_in_LE(&aux_int, BYTES_32BIT,fo);
	
	aux_int=AUDIO_FORMAT;
	write_in_LE(&aux_int, BYTES_16BIT,fo);
	
	aux_int=NUM_CHANNELS;
	write_in_LE(&aux_int, BYTES_16BIT,fo);
	
	aux_int=p_adt_wav->sample_frecuency;
	write_in_LE(&aux_int, BYTES_32BIT,fo);
	
	aux_int=(p_adt_wav->sample_frecuency)*2;
	write_in_LE(&aux_int, BYTES_32BIT,fo);
	
	aux_int=BLOCK_ALIGN;
	write_in_LE(&aux_int, BYTES_16BIT,fo);
	
	aux_int=BITS_PER_SAMPLE;
	write_in_LE(&aux_int, BYTES_16BIT,fo);
	
	write_in_LE(SUBCHUNK_2_ID, BYTES_32BIT,fo);
	
	aux_int=2*(p_adt_wav->samples_qty);
	write_in_LE(&aux_int, BYTES_32BIT,fo);
	
	j=p_adt_wav->samples_qty;
	for(i=0;i<j;i++){
		write_in_LE((p_adt_wav->samples)+i, BYTES_16BIT,fo);
	}
	
	return OK;
}
